﻿using System;
using System.IO;
using Mono.Cecil.Cil;
using Mono.Cecil.PE;

namespace Mono.Cecil
{
	// Token: 0x02000023 RID: 35
	internal static class ModuleWriter
	{
		// Token: 0x06000236 RID: 566 RVA: 0x00014108 File Offset: 0x00012308
		public static void WriteModule(ModuleDefinition module, Disposable<Stream> stream, WriterParameters parameters)
		{
			using (stream)
			{
				ModuleWriter.Write(module, stream, parameters);
			}
		}

		// Token: 0x06000237 RID: 567 RVA: 0x00014144 File Offset: 0x00012344
		private static void Write(ModuleDefinition module, Disposable<Stream> stream, WriterParameters parameters)
		{
			bool flag = (module.Attributes & ModuleAttributes.ILOnly) == (ModuleAttributes)0;
			if (flag)
			{
				throw new NotSupportedException("Writing mixed-mode assemblies is not supported");
			}
			bool flag2 = module.HasImage && module.ReadingMode == ReadingMode.Deferred;
			if (flag2)
			{
				ImmediateModuleReader immediateModuleReader = new ImmediateModuleReader(module.Image);
				immediateModuleReader.ReadModule(module, false);
				immediateModuleReader.ReadSymbols(module);
			}
			module.MetadataSystem.Clear();
			bool flag3 = module.symbol_reader != null;
			if (flag3)
			{
				module.symbol_reader.Dispose();
			}
			AssemblyNameDefinition assemblyNameDefinition = (module.assembly != null && module.kind != ModuleKind.NetModule) ? module.assembly.Name : null;
			string fileName = stream.value.GetFileName();
			uint timestamp = parameters.Timestamp ?? module.timestamp;
			ISymbolWriterProvider symbolWriterProvider = parameters.SymbolWriterProvider;
			bool flag4 = symbolWriterProvider == null && parameters.WriteSymbols;
			if (flag4)
			{
				symbolWriterProvider = new DefaultSymbolWriterProvider();
			}
			bool flag5 = parameters.HasStrongNameKey && assemblyNameDefinition != null;
			if (flag5)
			{
				assemblyNameDefinition.PublicKey = CryptoService.GetPublicKey(parameters);
				module.Attributes |= ModuleAttributes.StrongNameSigned;
			}
			bool deterministicMvid = parameters.DeterministicMvid;
			if (deterministicMvid)
			{
				module.Mvid = Guid.Empty;
			}
			MetadataBuilder metadataBuilder = new MetadataBuilder(module, fileName, timestamp, symbolWriterProvider);
			try
			{
				module.metadata_builder = metadataBuilder;
				using (ISymbolWriter symbolWriter = ModuleWriter.GetSymbolWriter(module, fileName, symbolWriterProvider, parameters))
				{
					metadataBuilder.SetSymbolWriter(symbolWriter);
					ModuleWriter.BuildMetadata(module, metadataBuilder);
					bool flag6 = symbolWriter != null;
					if (flag6)
					{
						symbolWriter.Write();
					}
					ImageWriter imageWriter = ImageWriter.CreateWriter(module, metadataBuilder, stream);
					stream.value.SetLength(0L);
					imageWriter.WriteImage();
					bool deterministicMvid2 = parameters.DeterministicMvid;
					if (deterministicMvid2)
					{
						ModuleWriter.ComputeDeterministicMvid(imageWriter, module);
					}
					bool hasStrongNameKey = parameters.HasStrongNameKey;
					if (hasStrongNameKey)
					{
						CryptoService.StrongName(stream.value, imageWriter, parameters);
					}
				}
			}
			finally
			{
				module.metadata_builder = null;
			}
		}

		// Token: 0x06000238 RID: 568 RVA: 0x00014358 File Offset: 0x00012558
		private static void BuildMetadata(ModuleDefinition module, MetadataBuilder metadata)
		{
			bool flag = !module.HasImage;
			if (flag)
			{
				metadata.BuildMetadata();
			}
			else
			{
				module.Read<MetadataBuilder, MetadataBuilder>(metadata, delegate(MetadataBuilder builder, MetadataReader _)
				{
					builder.BuildMetadata();
					return builder;
				});
			}
		}

		// Token: 0x06000239 RID: 569 RVA: 0x000143A4 File Offset: 0x000125A4
		private static ISymbolWriter GetSymbolWriter(ModuleDefinition module, string fq_name, ISymbolWriterProvider symbol_writer_provider, WriterParameters parameters)
		{
			bool flag = symbol_writer_provider == null;
			ISymbolWriter result;
			if (flag)
			{
				result = null;
			}
			else
			{
				bool flag2 = parameters.SymbolStream != null;
				if (flag2)
				{
					result = symbol_writer_provider.GetSymbolWriter(module, parameters.SymbolStream);
				}
				else
				{
					result = symbol_writer_provider.GetSymbolWriter(module, fq_name);
				}
			}
			return result;
		}

		// Token: 0x0600023A RID: 570 RVA: 0x000143E8 File Offset: 0x000125E8
		private static void ComputeDeterministicMvid(ImageWriter writer, ModuleDefinition module)
		{
			long position = writer.BaseStream.Position;
			writer.BaseStream.Seek(0L, SeekOrigin.Begin);
			Guid mvid = CryptoService.ComputeGuid(CryptoService.ComputeHash(writer.BaseStream));
			writer.MoveToRVA(TextSegment.GuidHeap);
			writer.WriteBytes(mvid.ToByteArray());
			writer.Flush();
			module.Mvid = mvid;
			writer.BaseStream.Seek(position, SeekOrigin.Begin);
		}
	}
}
